<?php
/**
 * 聊天管理
 * @author 银杏ERP
 * @version 1.0
 * @since 2025-03-28
 * @copyright 2025 红河州银杏科技有限公司
 * @license http://www.hhyx.xyz
 * @developer Lhf
 */
namespace app\admin\controller\yxerp;

use think\facade\Db;
use think\facade\Config;
use think\facade\Request;
use think\facade\Filesystem;
use app\common\controller\Backend;

class AIChat  extends Backend
{
    protected object $model_Message;
    protected object $model_Conversation;
    protected object $model_Attachment;
    protected object $model_Model;
    public function initialize(): void
    {
        parent::initialize();
        $this->model_Message = new \app\admin\model\yxerp\AiMessage();
        $this->model_Conversation = new \app\admin\model\yxerp\AiConversation();
        $this->model_Attachment = new \app\admin\model\yxerp\AiAttachment();
        $this->model_Model = new \app\admin\model\yxerp\AiModel();
    }
    /**
     * 获取用户的会话列表
     */
    public function getConversations()
    {
        $userId = request()->param('user_id/d', 0);
        if (empty($userId)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        $conversations = Db::name('yxerp_ai_conversations')
            ->where('user_id', $userId)
            ->field('id, title, model_id, message_count, last_message_time, create_time')
            ->order('last_message_time DESC')
            ->select()
            ->toArray();
        
        return json(['code' => 1, 'msg' => '获取成功', 'data' => $conversations]);
    }
    
    /**
     * 创建新会话
     */
    public function createConversation()
    {
        $data = $this->request->param();
        $userId = $data['user_id'] ?? 0;
        $title = $data['title'] ?? '新对话';
        $modelId = $data['model_id'] ?? 0;
        
        if (empty($userId) || empty($modelId)) {
            return json(['code' => 0, 'msg' => '用户ID和模型ID不能为空']);
        }
        
        // 检查模型是否存在
        $model = $this->model_Model->where('id', $modelId)->find();
        if (!$model) {
            return json(['code' => 0, 'msg' => '选择的模型不存在']);
        }
        
        $now = date('Y-m-d H:i:s');
        $conversationId = $this->model_Conversation->insertGetId([
            'user_id' => $userId,
            'title' => $title,
            'model_id' => $modelId,
            'last_message_time' => $now,
            'message_count' => 0
        ]);
        
        if ($conversationId) {
            // 如果有系统提示词，添加为系统消息
            if (!empty($systemPrompt)) {
                $this->model_Message->insert([
                    'conversation_id' => $conversationId,
                    'user_id' => $userId,
                    'role' => 'system',
                    'model_id' => $modelId
                ]);
            }
            
            return json(['code' => 1, 'msg' => '创建成功', 'data' => ['conversation_id' => $conversationId]]);
        } else {
            return json(['code' => 0, 'msg' => '创建失败']);
        }
    }
    
    /**
     * 获取会话详情
     */
    public function getConversation()
    {
        $id = request()->param('id/d', 0);
        if (empty($id)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        $conversation = Db::name('yxerp_ai_conversations')->where('id', $id)->find();
        if (!$conversation) {
            return json(['code' => 0, 'msg' => '会话不存在']);
        }
        
        // 获取关联的模型信息
        $model = Db::name('yxerp_ai_models')
            ->where('id', $conversation['model_id'])
            ->field('id, name, provider, model_type')
            ->find();
        
        $conversation['model'] = $model ?: [];
        
        return json(['code' => 1, 'msg' => '获取成功', 'data' => $conversation]);
    }
    
    /**
     * 更新会话信息
     */
    public function updateConversation()
    {
        $data = request()->post();
        $id = $data['id'] ?? 0;
        
        if (empty($id)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        $updateData = [];
        if (isset($data['title'])) {
            $updateData['title'] = $data['title'];
        }
        if (isset($data['system_prompt'])) {
            $updateData['system_prompt'] = $data['system_prompt'];
            
            // 更新系统提示消息
            $systemMessage = Db::name('yxerp_ai_messages')
                ->where('conversation_id', $id)
                ->where('role', 'system')
                ->order('id ASC')
                ->find();
            
            if ($systemMessage) {
                Db::name('yxerp_ai_messages')
                    ->where('id', $systemMessage['id'])
                    ->update(['content' => $data['system_prompt']]);
            } else if (!empty($data['system_prompt'])) {
                // 如果不存在系统消息但有提示词，创建一个
                Db::name('yxerp_ai_messages')->insert([
                    'conversation_id' => $id,
                    'user_id' => $data['user_id'] ?? $systemMessage['user_id'],
                    'role' => 'system',
                    'content' => $data['system_prompt'],
                    'model_id' => $data['model_id'] ?? $systemMessage['model_id'],
                    'create_time' => date('Y-m-d H:i:s')
                ]);
            }
        }
        if (isset($data['status'])) {
            $updateData['status'] = $data['status'];
        }
        
        if (!empty($updateData)) {
            $updateData['update_time'] = date('Y-m-d H:i:s');
            $result = Db::name('yxerp_ai_conversations')
                ->where('id', $id)
                ->update($updateData);
            
            if ($result !== false) {
                return json(['code' => 1, 'msg' => '更新成功']);
            } else {
                return json(['code' => 0, 'msg' => '更新失败']);
            }
        } else {
            return json(['code' => 0, 'msg' => '没有要更新的数据']);
        }
    }
    
    /**
     * 删除会话
     */
    public function deleteConversation()
    {
        $id = request()->param('id/d', 0);
        if (empty($id)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        Db::startTrans();
        try {
            // 先获取所有附件消息
            $attachmentMessages = Db::name('yxerp_ai_messages')
                ->where('conversation_id', $id)
                ->column('id');
            
            // 删除附件
            if (!empty($attachmentMessages)) {
                $attachments = Db::name('yxerp_ai_attachments')
                    ->where('message_id', 'in', $attachmentMessages)
                    ->select()
                    ->toArray();
                    
                foreach ($attachments as $attachment) {
                    if (!empty($attachment['file_path']) && file_exists(public_path() . $attachment['file_path'])) {
                        unlink(public_path() . $attachment['file_path']);
                    }
                    if (!empty($attachment['thumbnail']) && file_exists(public_path() . $attachment['thumbnail'])) {
                        unlink(public_path() . $attachment['thumbnail']);
                    }
                }
                
                Db::name('yxerp_ai_attachments')
                    ->where('message_id', 'in', $attachmentMessages)
                    ->delete();
            }
            
            // 删除消息
            Db::name('yxerp_ai_messages')
                ->where('conversation_id', $id)
                ->delete();
            
            // 删除会话
            Db::name('yxerp_ai_conversations')
                ->where('id', $id)
                ->delete();
            
            Db::commit();
            return json(['code' => 1, 'msg' => '删除成功']);
        } catch (\Exception $e) {
            Db::rollback();
            return json(['code' => 0, 'msg' => '删除失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 获取会话消息列表
     */
    public function getMessages()
    {
        $conversationId = request()->param('conversation_id/d', 0);
        $page = request()->param('page/d', 1);
        $limit = request()->param('limit/d', 20);
        
        if (empty($conversationId)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        $messages = $this->model_Message
            ->where('conversation_id', $conversationId)
            ->field('id, role, content, token_count, create_time')
            ->order('id DESC')
            ->page($page, $limit)
            ->select()
            ->toArray();
        
        // 获取附件
        $messageIds = array_column($messages, 'id');
        $attachments = [];
        
        if (!empty($messageIds)) {
            $attachmentList = $this->model_Attachment
                ->where('message_id', 'in', $messageIds)
                ->select()
                ->toArray();
            
            foreach ($attachmentList as $item) {
                $attachments[$item['message_id']][] = $item;
            }
        }
        
        // 处理消息，增加附件信息
        foreach ($messages as &$message) {
            if ($message['attachments'] && isset($attachments[$message['id']])) {
                $message['attachments'] = $attachments[$message['id']];
            } else {
                $message['attachments'] = [];
            }
        }
        
        // 重新按时间顺序排序
        usort($messages, function($a, $b) {
            return strtotime($a['create_time']) - strtotime($b['create_time']);
        });
        
        $total = Db::name('yxerp_ai_messages')
            ->where('conversation_id', $conversationId)
            ->count();
        
        return json([
            'code' => 1,
            'msg' => '获取成功',
            'data' => [
                'list' => $messages,
                'total' => $total,
                'page' => $page,
                'limit' => $limit
            ]
        ]);
    }
    
    /**
     * 发送消息并获取AI回复
     */
    public function sendMessage()
    {
        $data = $this->request->param();
        $conversationId = $data['conversation_id'] ?? 0;
        $content = isset($data['content']) ? trim($data['content']) : '';
        
        if (empty($conversation_id)) {
            return json(['code' => 0, 'msg' => '会话ID不能为空']);
        }
        
        // 获取会话信息
        $conversation = $this->model_Conversation
            ->where('id', $conversationId)
            ->find();
        
        if (!$conversation) {
            return json(['code' => 0, 'msg' => '会话不存在']);
        }
        
        // 获取模型信息
        $model = $this->model_Model
            ->where('id', $conversation['model_id'])
            ->find();
        
        if (!$model) {
            return json(['code' => 0, 'msg' => '模型不存在']);
        }

        $hasAttachments = isset($data['attachments']) && !empty($data['attachments']) ? 1 : 0;
        
        // 保存用户消息
        $messageId = $this->model_Message->insertGetId([
            'conversation_id' => $conversationId,
            'role' => 'user',
            'content' => $content,
            'model_id' => $conversation['model_id'],
        ]);
        
        // 处理附件
        if ($hasAttachments) {
            $this->processAttachments($messageId, $data['attachments']);
        }
        
        // 更新会话信息
        $this->model_Conversation
            ->where('id', $conversationId)
            ->update([
                'last_message_time' => time(),
                'message_count' => Db::raw('message_count + 1'),
            ]);
        
        // 获取历史消息
        $historyMessages = $this->getConversationHistory($conversationId);
        
        // 根据模型提供商调用不同的API
        try {
            $start = microtime(true);
            $response = $this->callAIModel($model, $historyMessages, $content, $hasAttachments ? $this->getAttachmentUrls($messageId) : []);
            $responseTime = round((microtime(true) - $start) * 1000); // 毫秒
            
            // 保存AI回复
            $aiMessageId = Db::name('yxerp_ai_messages')->insertGetId([
                'conversation_id' => $conversationId,
                'user_id' => $userId,
                'role' => 'assistant',
                'content' => $response['content'],
                'raw_content' => $response['raw_content'] ?? '',
                'token_count' => $response['token_count'] ?? 0,
                'model_id' => $conversation['model_id'],
                'response_time' => $responseTime,
                'create_time' => date('Y-m-d H:i:s')
            ]);
            
            // 再次更新会话信息
            Db::name('yxerp_ai_conversations')
                ->where('id', $conversationId)
                ->update([
                    'last_message_time' => date('Y-m-d H:i:s'),
                    'message_count' => Db::raw('message_count + 1'),
                    'update_time' => date('Y-m-d H:i:s')
                ]);
            
            return json([
                'code' => 1,
                'msg' => '发送成功',
                'data' => [
                    'message_id' => $messageId,
                    'ai_message_id' => $aiMessageId,
                    'content' => $response['content'],
                    'response_time' => $responseTime
                ]
            ]);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '模型调用失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 上传附件
     */
    public function uploadAttachment()
    {
        $file = request()->file('file');
        if (!$file) {
            return json(['code' => 0, 'msg' => '未上传文件']);
        }
        
        $type = request()->param('type/s', 'file');
        $validate = [
            'size' => 10 * 1024 * 1024, // 10MB
        ];
        
        if ($type === 'image') {
            $validate['ext'] = 'jpg,jpeg,png,gif,webp';
            $dirname = 'uploads/ai/images/' . date('Ymd');
        } else {
            $validate['ext'] = 'txt,pdf,doc,docx,xls,xlsx,ppt,pptx,zip,rar,7z,md';
            $dirname = 'uploads/ai/files/' . date('Ymd');
        }
        
        try {
            $savename = Filesystem::disk('public')->putFile($dirname, $file, 'uniqid');
            $savepath = '/storage/' . $savename;
            $fileInfo = $file->getInfo();
            
            $result = [
                'code' => 1, 
                'msg' => '上传成功',
                'data' => [
                    'url' => $savepath,
                    'name' => $fileInfo['name'],
                    'size' => $fileInfo['size'],
                    'type' => $type,
                    'mime_type' => $file->getMime(),
                    'ext' => pathinfo($fileInfo['name'], PATHINFO_EXTENSION)
                ]
            ];
            
            // 如果是图片类型，生成缩略图
            if ($type === 'image') {
                try {
                    $image = \think\Image::open(public_path() . $savepath);
                    $thumbPath = dirname($savepath) . '/thumb_' . basename($savepath);
                    $image->thumb(200, 200)->save(public_path() . $thumbPath);
                    $result['data']['thumbnail'] = $thumbPath;
                } catch (\Exception $e) {
                    // 缩略图生成失败，使用原图
                    $result['data']['thumbnail'] = $savepath;
                }
            }
            
            return json($result);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '上传失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 处理附件
     */
    private function processAttachments($messageId, $attachments)
    {
        if (empty($attachments) || !is_array($attachments)) {
            return;
        }
        
        foreach ($attachments as $attachment) {
            Db::name('yxerp_ai_attachments')->insert([
                'message_id' => $messageId,
                'type' => $attachment['type'] ?? 'file',
                'original_name' => $attachment['name'] ?? '',
                'file_path' => isset($attachment['url']) ? str_replace('/storage/', '', $attachment['url']) : '',
                'file_size' => $attachment['size'] ?? 0,
                'file_ext' => $attachment['ext'] ?? '',
                'url' => $attachment['type'] === 'url' ? $attachment['url'] : '',
                'thumbnail' => isset($attachment['thumbnail']) ? str_replace('/storage/', '', $attachment['thumbnail']) : '',
                'mime_type' => $attachment['mime_type'] ?? '',
                'create_time' => date('Y-m-d H:i:s')
            ]);
        }
    }
    
    /**
     * 获取附件URL列表
     */
    private function getAttachmentUrls($messageId)
    {
        $attachments = Db::name('yxerp_ai_attachments')
            ->where('message_id', $messageId)
            ->select()
            ->toArray();
        
        $urls = [];
        foreach ($attachments as $attachment) {
            if ($attachment['type'] === 'url') {
                $urls[] = $attachment['url'];
            } else {
                $urls[] = request()->domain() . '/storage/' . $attachment['file_path'];
            }
        }
        
        return $urls;
    }
    
    /**
     * 获取会话历史消息
     */
    private function getConversationHistory($conversationId)
    {
        $messages = $this->model_Message
            ->where('conversation_id', $conversationId)
            ->field('role, content')
            ->order('id ASC')
            ->select()
            ->toArray();
        
        return $messages;
    }
    
    /**
     * 调用AI模型
     */
    private function callAIModel($model, $history, $content, $attachmentUrls = [])
    {
        $provider = $model['provider'];
        $apiKey = $this->decryptApiKey($model['api_key']);
        $endpoint = $model['endpoint_url'];
        
        switch ($provider) {
            case 'openai':
                return $this->callOpenAI($endpoint, $apiKey, $model, $history, $content, $attachmentUrls);
            case 'azure':
                return $this->callAzure($endpoint, $apiKey, $model, $history, $content, $attachmentUrls);
            case 'anthropic':
                return $this->callAnthropic($endpoint, $apiKey, $model, $history, $content, $attachmentUrls);
            default:
                throw new \Exception('不支持的模型提供商');
        }
    }
    
    /**
     * 调用OpenAI API
     */
    private function callOpenAI($endpoint, $apiKey, $model, $history, $content, $attachmentUrls = [])
    {
        $curl = curl_init();
        $headers = [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey
        ];
        
        $params = json_decode($model['params'] ?: '{}', true);
        $modelName = $params['model_name'] ?? 'gpt-3.5-turbo';
        
        // 准备消息
        $messages = [];
        foreach ($history as $msg) {
            $messages[] = [
                'role' => $msg['role'],
                'content' => $msg['content']
            ];
        }
        
        // 如果有附件URL，添加到内容中
        $userContent = $content;
        if (!empty($attachmentUrls)) {
            $userContent .= "\n\n参考的链接/文件:\n" . implode("\n", $attachmentUrls);
        }
        
        // 添加当前用户消息
        $messages[] = [
            'role' => 'user',
            'content' => $userContent
        ];
        
        $data = [
            'model' => $modelName,
            'messages' => $messages,
            'temperature' => floatval($params['temperature'] ?? 0.7),
            'max_tokens' => intval($params['max_tokens'] ?? 2000),
            'top_p' => floatval($params['top_p'] ?? 1.0),
            'frequency_penalty' => floatval($params['frequency_penalty'] ?? 0),
            'presence_penalty' => floatval($params['presence_penalty'] ?? 0)
        ];
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $endpoint . '/v1/chat/completions',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => $headers,
        ]);
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        
        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }
        
        if ($httpCode >= 400) {
            $responseData = json_decode($response, true);
            $errorMsg = isset($responseData['error']['message']) 
                ? $responseData['error']['message'] 
                : 'API Error: HTTP ' . $httpCode;
            throw new \Exception($errorMsg);
        }
        
        $responseData = json_decode($response, true);
        
        return [
            'content' => $responseData['choices'][0]['message']['content'],
            'raw_content' => $response,
            'token_count' => $responseData['usage']['total_tokens'] ?? 0
        ];
    }
    
    /**
     * 调用Azure OpenAI API
     */
    private function callAzure($endpoint, $apiKey, $model, $history, $content, $attachmentUrls = [])
    {
        $curl = curl_init();
        $headers = [
            'Content-Type: application/json',
            'api-key: ' . $apiKey
        ];
        
        $params = json_decode($model['params'] ?: '{}', true);
        $deploymentId = $params['deployment_id'] ?? 'gpt35';
        $apiVersion = $params['api_version'] ?? '2023-05-15';
        
        // 准备消息
        $messages = [];
        foreach ($history as $msg) {
            $messages[] = [
                'role' => $msg['role'],
                'content' => $msg['content']
            ];
        }
        
        // 如果有附件URL，添加到内容中
        $userContent = $content;
        if (!empty($attachmentUrls)) {
            $userContent .= "\n\n参考的链接/文件:\n" . implode("\n", $attachmentUrls);
        }
        
        // 添加当前用户消息
        $messages[] = [
            'role' => 'user',
            'content' => $userContent
        ];
        
        $data = [
            'messages' => $messages,
            'temperature' => floatval($params['temperature'] ?? 0.7),
            'max_tokens' => intval($params['max_tokens'] ?? 2000),
            'top_p' => floatval($params['top_p'] ?? 1.0),
            'frequency_penalty' => floatval($params['frequency_penalty'] ?? 0),
            'presence_penalty' => floatval($params['presence_penalty'] ?? 0)
        ];
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $endpoint . '/openai/deployments/' . $deploymentId . '/chat/completions?api-version=' . $apiVersion,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => $headers,
        ]);
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        
        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }
        
        if ($httpCode >= 400) {
            $responseData = json_decode($response, true);
            $errorMsg = isset($responseData['error']['message']) 
                ? $responseData['error']['message'] 
                : 'API Error: HTTP ' . $httpCode;
            throw new \Exception($errorMsg);
        }
        
        $responseData = json_decode($response, true);
        
        return [
            'content' => $responseData['choices'][0]['message']['content'],
            'raw_content' => $response,
            'token_count' => $responseData['usage']['total_tokens'] ?? 0
        ];
    }
    
    /**
     * 调用Anthropic API
     */
    private function callAnthropic($endpoint, $apiKey, $model, $history, $content, $attachmentUrls = [])
    {
        $curl = curl_init();
        $headers = [
            'Content-Type: application/json',
            'x-api-key: ' . $apiKey,
            'anthropic-version: 2023-06-01'
        ];
        
        $params = json_decode($model['params'] ?: '{}', true);
        $modelName = $params['model_name'] ?? 'claude-2';
        
        // 构建Anthropic格式的对话
        $prompt = "";
        foreach ($history as $msg) {
            if ($msg['role'] == 'user') {
                $prompt .= "\n\nHuman: " . $msg['content'];
            } else if ($msg['role'] == 'assistant') {
                $prompt .= "\n\nAssistant: " . $msg['content'];
            }
        }
        
        // 如果有附件URL，添加到内容中
        $userContent = $content;
        if (!empty($attachmentUrls)) {
            $userContent .= "\n\n参考的链接/文件:\n" . implode("\n", $attachmentUrls);
        }
        
        // 添加当前用户消息
        $prompt .= "\n\nHuman: " . $userContent . "\n\nAssistant:";
        
        $data = [
            'model' => $modelName,
            'prompt' => $prompt,
            'max_tokens_to_sample' => intval($params['max_tokens'] ?? 2000),
            'temperature' => floatval($params['temperature'] ?? 0.7),
            'top_p' => floatval($params['top_p'] ?? 1.0),
        ];
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $endpoint . '/v1/complete',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => $headers,
        ]);
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        
        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }
        
        if ($httpCode >= 400) {
            $responseData = json_decode($response, true);
            $errorMsg = isset($responseData['error']['message']) 
                ? $responseData['error']['message'] 
                : 'API Error: HTTP ' . $httpCode;
            throw new \Exception($errorMsg);
        }
        
        $responseData = json_decode($response, true);
        
        return [
            'content' => $responseData['completion'],
            'raw_content' => $response,
            'token_count' => $responseData['stop_reason'] === 'max_tokens' ? $params['max_tokens'] : 0
        ];
    }
    
    /**
     * 加密API密钥
     */
    private function encryptApiKey($key)
    {
        return openssl_encrypt(
            $key,
            'AES-256-CBC',
            Config::get('app.app_key'),
            0,
            substr(Config::get('app.app_key'), 0, 16)
        );
    }
    
    /**
     * 解密API密钥
     */
    private function decryptApiKey($encrypted)
    {
        return openssl_decrypt(
            $encrypted,
            'AES-256-CBC',
            Config::get('app.app_key'),
            0,
            substr(Config::get('app.app_key'), 0, 16)
        );
    }

    
/**
 * 获取Ollama可用模型列表
 */
public function getOllamaModels()
{
    $endpoint = request()->param('endpoint', 'http://localhost:11434');
    
    try {
        $client = new \GuzzleHttp\Client();
        $response = $client->get($endpoint.'/api/tags');
        $data = json_decode($response->getBody(), true);
        
        return json(['code' => 1, 'msg' => '获取成功', 'data' => $data['models'] ?? []]);
    } catch (\Exception $e) {
        return json(['code' => 0, 'msg' => '获取失败：'.$e->getMessage()]);
    }
}
} 